/*这个只是为了从fpga向PC发送32位数据的一个传送版本，使用了add_reg计数+1技术。实验的结果表明，如果并口不通过并口延长线直接连结PC端的并口时，数据似乎是正确的。
但是addr_reg清零似乎一下不够，要清好几下才行。数据发送的顺序正确的。这是一个可以用来细细研究的版本，但是因为现在要做项目。我还是返回原先的v3版本比较好。*/
module EPPv3(clk, led, IOdir, lvc_dir, pport_data, nWrite, nWait, nDataStr, nAddrStr,step,dir);
    parameter W=10;
    parameter F=11;
    parameter T=4;
input clk;
output led, IOdir,lvc_dir;//dir是其中一个lvc4245的片选，hsy其实没用只是永远高电平
assign lvc_dir = 1;// A=>B 
inout [7:0] pport_data;//注意读写都是在这个双向口上，PC与FPGA通信
input nWrite;
output nWait;
input nDataStr, nAddrStr;
wire real_step; output step = do_tristate ? 1'bZ : real_step;
wire real_dir; output dir = do_tristate ? 1'bZ : real_dir;
wire[W+F-1:0] pos0;
reg[F:0] vel0;
reg[T-1:0] dirtime, steptime;
reg[1:0] tap;

reg [10:0] div2048;
wire stepcnt = ~|(div2048[5:0]);

always @(posedge clk) begin//脉冲的基频
    div2048 <= div2048 + 1'd1;
end
wire do_enable_wdt, do_tristate;
wdt w(clk, do_enable_wdt, &div2048, do_tristate);
stepgen #(W,F,T) s0(clk, stepcnt, pos0, vel0, dirtime, steptime, real_step, real_dir, tap);
// EPP stuff
wire EPP_write = ~nWrite;
wire EPP_read =  nWrite;
wire EPP_addr_strobe = ~nAddrStr;
wire EPP_data_strobe = ~nDataStr;
wire EPP_strobe = EPP_data_strobe | EPP_addr_strobe;

wire EPP_wait; assign nWait = EPP_wait;
wire [7:0] EPP_datain = pport_data;//8位并口的数据！！！！！
wire [7:0] EPP_dataout; assign pport_data = EPP_dataout;

reg [4:0] EPP_strobe_reg;//这里做的事情称作同步。EPP_strobe_reg在00100这样的信号中检测有无数据选通，很核心
always @(posedge clk) EPP_strobe_reg <= {EPP_strobe_reg[3:0], EPP_strobe};
wire EPP_strobe_edge1 = (EPP_strobe_reg[2:1]==2'b01);//一个上升，表示数据选通。

reg led;
reg[4:0] addr_reg;//addr_reg这个寄存器似乎是一个来自地址线的计数，从1,2,3,4这样不断的累加。
assign EPP_wait = EPP_strobe_reg[4];//？？？？？？？？？？？？？？
wire[15:0] EPP_dataword = {EPP_datain, lowbyte};//这是两个byte在这里变成一个word.
reg[7:0] lowbyte;

always @(posedge clk)//一个计数和清零的东西
    if(EPP_strobe_edge1 & EPP_write & EPP_addr_strobe) begin//请区别这里是地址写！！！！
        addr_reg <= 0;//EPP_datain[4:0];//由于我们在PC端只是EPP_ADDR(0),因而可以看作清零吧。
    end
    else if(EPP_strobe_edge1 & !EPP_addr_strobe) addr_reg <= addr_reg + 4'd1;
    //上句其实只是起到了计数的作用。我认为只是在数据读或写的时候+1这样以来。考虑到我们每次数据的
    //读写都是以2byte（16）,或4byte（32）为单位。那么我们就很容易通过奇偶来判断哪个是高byte，哪个是低byte.
always @(posedge clk) begin//数据写的关键步骤。
    if(EPP_strobe_edge1 & EPP_write & EPP_data_strobe) begin//请区别这里是数据写！！！！
         //led<=~led;
         if(addr_reg[3:0] == 4'd1)      vel0 <= EPP_dataword[F:0];
         else if(addr_reg[3:0] == 4'd3)//第二个word用来传送一些额外的信息。
            begin
                steptime <= lowbyte[T-1:0];
                tap <= lowbyte[7:6];
                dirtime <= EPP_datain[T-1:0];
            end
         else  
			lowbyte <= EPP_datain;
		  //led <= ~led;
	 
    end
end

reg [31:0] data_buf;

always @(posedge clk) begin
    if(EPP_strobe_edge1 & EPP_read & EPP_data_strobe/*&&addr_reg[1:0] == 2'd0*/) begin
		 
      if(addr_reg[4:2] == 3'd0) data_buf[31:0] <= 32'hffaced9b;
      //else if(addr_reg[4:2] == 3'd1) data_buf <= pos1;
      //else if(addr_reg[4:2] == 3'd2) data_buf <= pos2;
      //else if(addr_reg[4:2] == 3'd3) data_buf <= pos3;
      //else if(addr_reg[4:2] == 3'd4)
            //data_buf <= din;
    end
	 
end
// the addr_reg test looks funny because it is auto-incremented in an always
// block so "1" reads the low byte, "2 and "3" read middle bytes, and "0"
// reads the high byte I have a feeling that I'm doing this in the wrong way.
wire [7:0] data_reg = addr_reg[4:0] == 2'd1 ? data_buf[7:0] :
								(addr_reg[4:0] == 2'd2 ? data_buf[15:8] :
                         (addr_reg[4:0] == 2'd3 ? data_buf[23:16] :
                         data_buf[31:24]));
//reg [7:0] data_reg; 				 
wire [7:0] EPP_data_mux = data_reg;
assign EPP_dataout = (EPP_read & EPP_wait) ? EPP_data_mux : 8'hZZ;
wire IOdir=~EPP_read;//EPP_read是并口过来的控制信号，这里也要控制lvc4245的方向。
assign do_enable_wdt = EPP_strobe_edge1 & EPP_write & EPP_data_strobe;
endmodule
